﻿package com.plter.controls.asmax
{
	import com.plter.events.AScrollBarEvent;
	
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/**
	 * 垂直滚动条组件
	 * @author Jaja as-max.cn
	 */
	internal class AScrollBarBase extends Sprite 
	{
		private var upArrow:ArrowButton = new ArrowButton;
		private var scroll:ScrolledBar = new ScrolledBar;
		private var downArrow:ArrowButton = new ArrowButton;
		private var bg:Sprite = new Sprite;
		private var dragStratY:Number = 0;
		private var dragStartMouseY:Number = 0;
		/**
		 * 滚动条可滚动的区域的高度
		 */
		private var scrolledAreaHeight:Number = 70;
		
		/**
		 * 滚动条滑块上一次的位置
		 */
		private var lastBarPosition:Number = 0;
		
		/**
		 * 滚动条速度
		 */
		private var scrollSpeedY:int = 3;
		/**
		 * 滚动条的作用区域
		 */
		private var theFuncArea:InteractiveObject;
		
		public function AScrollBarBase() :void
		{
			//build bg
			bg.graphics.beginFill(0xDEDEDE);
			bg.graphics.drawRect(0, 0, 16, 100);
			bg.graphics.endFill();
			super.addChild(bg);
			bg.x = -0.5;
			bg.y = -0.5;
			
			//add children
			super.addChild(upArrow);
			super.addChild(scroll);
			downArrow.rotation = 180;
			super.addChild(downArrow);
			
			fixLayout();
			
			//add listeners
			upArrow.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
			downArrow.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
			scroll.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
			bg.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
		}
		
		/**
		 * 获得组件的高度
		 */
		public override function get height():Number { return super.height; }
		/**
		 * 设置组件的高度,此高度不能小于45
		 */
		public override  function set height(value:Number):void 
		{
			if (value < 50) {
				throw new Error("此滚动条组件的高度不能小于50像素");
			}
			
			scroll.height = value-34;
			scrolledAreaHeight = value-34;
			fixLayout();
		}
		
		/**
		 * 指示此组件的宽度
		 */
		public override function get width():Number { return super.width; }
		/**
		 * 指示此组件的宽度
		 */
		public override  function set width(value:Number):void 
		{
			upArrow.width = value;
			downArrow.width = value;
			bg.width = value;
			scroll.width = value;
			
			fixLayout();
		}
		
		/**
		 * 设置滚动条的缩放比例,0到1之间的数值
		 * @param	value	一个0到1之间数值
		 */
		public function set barScale(value:Number):void {
			if (value <= 0) {
				throw new Error("滑块的缩放比例必须为一个0到1之间的数值");
			}
			if (value > 1) {
				throw new Error("滑块的缩放比例必须为一个0到1之间的数值");
			}
			
			scroll.scaleY = value;
			if (scroll.height < 10) {
				scroll.scaleY = 10 / scrolledAreaHeight;
			}
			
			if (scroll.y > downArrow.y - downArrow.height - scroll.height) {
				scroll.y = downArrow.y - downArrow.height - scroll.height;
			}
			if (scroll.y < upArrow.y + upArrow.height) {
				scroll.y = upArrow.y + upArrow.height;
			}
		}
		/**
		 * 获得滑块的缩放比例
		 */
		public function get barScale():Number {
			return scroll.scaleY;
		}
		
		/**
		 * 设置滚动条的作用区域
		 */
		public function set funcArea(value:InteractiveObject):void {
			try{
				theFuncArea.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseEventHandler);
			}catch (error:Error) {
				//theFuncArea尚未设置,忽略此错误
			}
			theFuncArea = value;
			theFuncArea.addEventListener(MouseEvent.MOUSE_WHEEL, mouseEventHandler);
		}
		/**
		 * 获得滚动条的作用区域
		 */
		public function get funcArea():InteractiveObject {
			return theFuncArea;
		}
		
		/**
		 * 设置滚动条的位置,为0到1之间的数值
		 * @param	value	0到1之间的数值
		 */
		public function set position(value:Number):void {
			scroll.y = (downArrow.y - downArrow.height - upArrow.y - upArrow.height - scroll.height) * value + upArrow.y + upArrow.height;
			fixBarLocationY();
		}
		/**
		 * 获得滚动条的位置,为0到1之间的数值
		 */
		public function get position():Number {
			return (scroll.y - upArrow.y - upArrow.height) / (downArrow.y - downArrow.height - upArrow.y - upArrow.height - scroll.height);
		}
		
		public override function addChild(child:DisplayObject):DisplayObject 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			return super.addChild(child);
		}
		
		public override function addChildAt(child:DisplayObject, index:int):DisplayObject 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			return super.addChildAt(child, index);
		}
		
		public override function removeChild(child:DisplayObject):DisplayObject 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			return super.removeChild(child);
		}
		
		public override function removeChildAt(index:int):DisplayObject 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			return super.removeChildAt(index);
		}
		
		public override function setChildIndex(child:DisplayObject, index:int):void 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			super.setChildIndex(child, index);
		}
		
		public override function swapChildren(child1:DisplayObject, child2:DisplayObject):void 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			super.swapChildren(child1, child2);
		}
		
		public override function swapChildrenAt(index1:int, index2:int):void 
		{
			throw AsmaxErrors.DISUSE_METHOD_ERROR;
			super.swapChildrenAt(index1, index2);
		}
		
		/**
		 * 固定布局
		 */
		private function fixLayout():void {
			scroll.y = upArrow.y + upArrow.height;
			downArrow.y = scroll.y + scrolledAreaHeight + downArrow.height;
			downArrow.x = scroll.x + downArrow.width - 1;
			
			bg.height = scrolledAreaHeight + upArrow.height + downArrow.height;
		}
		
		/**
		 * 鼠标滑轮滚动事件的处理器
		 * @param	event
		 */
		private function mouseEventHandler(event:MouseEvent):void {
			switch(event.type) {
				case MouseEvent.MOUSE_WHEEL:
					scroll.y -= event.delta;
					
					fixBarLocationY();
					break;
				case MouseEvent.MOUSE_DOWN:
					if (mouseY < scroll.y) {
						scrollSpeedY = -Math.abs(scrollSpeedY); 
						
						stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
						addEventListener(Event.ENTER_FRAME, enterFrame);
					}else if (mouseY < scroll.y + scroll.height) {
						dragStartMouseY = mouseY;
						dragStratY = scroll.y;
						
						stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
						stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
					}else {
						scrollSpeedY = Math.abs(scrollSpeedY); 
						
						stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
						addEventListener(Event.ENTER_FRAME, enterFrame);
					}
					break;
				case MouseEvent.MOUSE_UP:
					removeEventListener(Event.ENTER_FRAME, enterFrame);
					stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
					stage.removeEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
					break;
			}
		}
		
		private function enterFrame(event:Event):void {
			scroll.y += scrollSpeedY;
			fixBarLocationY();
			
			if (mouseY > scroll.y && mouseY < scroll.y + scroll.height) {
				removeEventListener(Event.ENTER_FRAME, enterFrame);
			}
		}
		
		private function mouseMove(event:MouseEvent):void {
			scroll.y = mouseY - dragStartMouseY + dragStratY;
			
			fixBarLocationY();
		}
		
		/**
		 * 固定滚动条的y坐标
		 */
		private function fixBarLocationY():void {
			if (scroll.y > downArrow.y - downArrow.height - scroll.height) {
				scroll.y = downArrow.y - downArrow.height - scroll.height;
			}
			if (scroll.y < upArrow.y + upArrow.height) {
				scroll.y = upArrow.y + upArrow.height;
			}
			
			dispatchScrollBarEvent(position);
		}
		
		/**
		 * 当滚动条滑块位置变动时触发此事件
		 * @param	position 
		 * @eventType cn.asmax.events.ScrollBarEvent.SCROLL
		 */
		[Event(name="scroll",type="cn.asmax.events.ScrollBarEvent")]
		private function dispatchScrollBarEvent(position:Number):void {
			//如果此次位置与上次位置相同,则不触发事件
			if (position == lastBarPosition) {
				return;
			}
			//触发事件
			var evt:AScrollBarEvent = new AScrollBarEvent(AScrollBarEvent.SCROLL);
			evt.position = position;
			dispatchEvent(evt);
			//记录此次位置
			lastBarPosition = position;
		}
		
	}
	
}


import flash.display.Shape;
import flash.display.Sprite;
import flash.events.MouseEvent;

class ScrolledBar extends Sprite {
	
	private var thisHeight:uint = 70;
	/**
	 * 滚动条的中间可拖动部分
	 */
	public function ScrolledBar():void {
		drawBar(0xF9F9F9, 0xEEEEEE);
		
		this.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
		this.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
	}
	
	private function mouseOver(event:MouseEvent):void {
		drawBar(0xEEEEEE, 0xDDDDDD);
	}
	
	private function mouseOut(event:MouseEvent):void {
		drawBar(0xF9F9F9, 0xEEEEEE);
	}
	
	public override function get height():Number { return super.height; }
	
	public override  function set height(value:Number):void 
	{
		drawBar(0xF9F9F9, 0xEEEEEE, value);
	}
	
	/**
	 * 绘制滚动块
	 * @param	fillColor	填充颜色
	 * @param	lineColor	线条颜色
	 * @param	h	高度
	 */
	private function drawBar(fillColor:uint = 0, lineColor:uint = 0, h:uint = 0):void {
		if (h != 0) {
			thisHeight = h;
		}
		
		graphics.clear();
		graphics.beginFill(fillColor);
		graphics.lineStyle(1, lineColor);
		graphics.drawRect(0, 0, 15, thisHeight);
		graphics.endFill();
	}
}



class ArrowButton extends Sprite {
	
	private var bg:Shape = new Shape;
	private var arrow:Shape = new Shape;
	
	/**
	 * 箭头按钮
	 */
	public function ArrowButton():void {
		drawBG(0xF9F9F9, 0xEEEEEE);
		addChild(bg);
		
		drawArrow(0xAAAAAA, 0xAAAAAA);
		addChild(arrow);
		
		this.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
		this.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
	}
	
	private function mouseOver(event:MouseEvent):void {
		drawBG(0xEEEEEE, 0xDDDDDD);
	}
	
	private function mouseOut(event:MouseEvent):void {
		drawBG(0xF9F9F9, 0xEEEEEE);
	}
	
	private function drawBG(fillColor:uint, lineColor:uint):void {
		bg.graphics.clear();
		bg.graphics.beginFill(fillColor);
		bg.graphics.lineStyle(1, lineColor);
		bg.graphics.drawRect(0, 0, 15, 15);
		bg.graphics.endFill();
	}
	
	private function drawArrow(fillColor:uint, lineColor:uint):void {
		arrow.graphics.clear();
		arrow.graphics.beginFill(fillColor);
		arrow.graphics.lineStyle(1, lineColor);
		arrow.graphics.moveTo(7.5, 6);
		arrow.graphics.lineTo(11.5, 9);
		arrow.graphics.lineTo(3.5, 9);
		arrow.graphics.lineTo(7.5, 6);
		arrow.graphics.endFill();
	}
}